
use anyhow::Result;
use hyper::{Request, Response, Client, body};
use hyper::client::HttpConnector;
use std::collections::HashMap;

use serde::{Deserialize, Serialize};
use std::borrow::Borrow;

use crate::miner::{JsonRpcResponse, JsonRpcError};
use crate::miner::types::TaskType;

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct WorkerResource {
    pub mem_physical: u64,
    pub mem_swap: u64,
    pub mem_reserved: u64,
    #[serde(rename(deserialize = "CPUs"))]
    pub cpus: u32,
    #[serde(rename(deserialize = "GPUs"))]
    pub gpus: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct WorkerInfo {
    pub hostname: String,
    pub ignore_resources: bool,
    pub resources: WorkerResource,
    pub work_limit: HashMap<TaskType, u32>,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct SealWorkerStats {
    pub info: WorkerInfo,
    pub enabled: bool,
    pub mem_used_min: u64,
    pub mem_used_max: u64,
    pub gpu_used: bool,
    pub cpu_use: u32,
    pub task_support: HashMap<TaskType, u32>,
}

pub async fn query_worker_from_miner(client: &Client<HttpConnector>, url: &str, token: &str) -> Result<JsonRpcResponse<HashMap<String, SealWorkerStats>>>{
    let body = r#"
{
	"jsonrpc": "2.0",
	"method": "Filecoin.WorkerStats",
	"params": [],
	"id": 1
}
"#;
    let auth = format!("Bearer {}", token);
    let body = body::Body::from(body);

    let request = Request::builder()
        .uri(url)
        .header("Authorization", auth)
        .body(body)?;

    let rsp = client.request(request).await?;
    if rsp.status().is_success() {
        let buf = body::to_bytes(rsp).await?;
        let result: JsonRpcResponse<HashMap<String, SealWorkerStats>> = serde_json::from_slice(buf.borrow())?;
        Ok(result)
    } else {
        Err(anyhow::Error::msg(format!("http request got error response {}", rsp.status())))
    }
}